package com.self.cloudmall.cart.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.self.cloudmall.cart.bo.UserCartBo;
import com.self.cloudmall.cart.client.SkuClient;
import com.self.cloudmall.cart.service.CartService;
import com.self.cloudmall.cart.vo.CartItemVo;
import com.self.cloudmall.cart.vo.CartVo;
import com.self.cloudmall.common.constant.CartConstant;
import com.self.cloudmall.common.dto.CartItemCheckedDto;
import com.self.cloudmall.common.dto.SkuInfoDto;
import com.self.cloudmall.common.utils.R;
import com.self.cloudmall.common.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @version v1.0
 * @ClassName: CartServiceImpl
 * @Description:
 * @Author: M10003729
 */
@Service
@Slf4j
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private SkuClient skuClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Override
    public CartItemVo addToCart(Long skuId, Integer num) {
        try {
            BoundHashOperations cartOps = redisCartOps();
            //如果sku存在，则更新数量
            Object o = cartOps.get(skuId + "");
            if (o != null){
                CartItemVo cartItem = JSONObject.parseObject(JSONObject.toJSONString(o),CartItemVo.class);
                cartItem.setCount(cartItem.getCount()+num);
                cartOps.put(skuId+"",cartItem);
                return cartItem;
            }

            CartItemVo itemVo = new CartItemVo();
            //设置sku信息
            CompletableFuture<Void> skuInfoFuture = CompletableFuture.runAsync(() -> {
                R info = skuClient.info(skuId);
                if (info.isSuccess()){
                    SkuInfoDto skuInfo = JSONObject.parseObject(JSONObject.toJSONString(info.get("skuInfo")), SkuInfoDto.class);
                    itemVo.setChecked(true);
                    itemVo.setCount(num);
                    itemVo.setImage(skuInfo.getSkuDefaultImg());
                    itemVo.setPrice(skuInfo.getPrice());
                    itemVo.setSkuId(skuId);
                    itemVo.setSkuTitle(skuInfo.getSkuTitle());
                }
            }, threadPoolExecutor);

            //设置商品属性
            CompletableFuture<Void> saleAttrFuture =CompletableFuture.runAsync(()->{
                R saleAttrs = skuClient.getSaleAttrs(skuId);
                if (saleAttrs.isSuccess()){
                    Object data = saleAttrs.getData();
                    List<String> attrs = JSONObject.parseObject(JSONObject.toJSONString(data), new TypeReference<List<String>>() {
                    });
                    itemVo.setSkuAttrs(attrs);
                }
            },threadPoolExecutor);
            CompletableFuture.allOf(skuInfoFuture,saleAttrFuture).get();
            //放入缓存
            cartOps.put(skuId+"",itemVo);

            return itemVo;
        } catch (Exception e) {
           log.error("购物车获取sku信息异常：",e);
        }
        return null;
    }

    @Override
    public CartItemVo getCartItem(Long skuId) {
        BoundHashOperations cartOps = redisCartOps();
        Object o = cartOps.get(skuId + "");
        return JSONObject.parseObject(JSONObject.toJSONString(o),CartItemVo.class);
    }

    @Override
    public CartVo getCart() {
        UserCartBo userCart = ThreadLocalUtil.get();
        CartVo cartVo = new CartVo();
        String tempCartKey = null;
        if (userCart.getUserId() != null){
            //登录，则合并临时购物，最后清空临时购物车
            String cartKey = CartConstant.CART_REDIS_PREFIX + userCart.getUserId();
            //获取临时购物车
            tempCartKey = CartConstant.CART_REDIS_PREFIX + userCart.getUserKey();
            List<CartItemVo> cartItemList = getCartItemList(tempCartKey);
            if (!CollectionUtils.isEmpty(cartItemList)){
                //合并购物
                cartItemList.forEach(x -> {
                    addToCart(x.getSkuId(),x.getCount());
                });
                //清空购物车
                redisTemplate.delete(tempCartKey);
            }
            //获取最新在线购物车
            cartItemList = getCartItemList(cartKey);
            cartVo.setItems(cartItemList);
        }else{
            //没登录，直接返回临时购物车
            tempCartKey = CartConstant.CART_REDIS_PREFIX + userCart.getUserKey();
            List<CartItemVo> cartItemList = getCartItemList(tempCartKey);
            if (!CollectionUtils.isEmpty(cartItemList)){
                cartVo.setItems(cartItemList);
            }
        }
        return cartVo;
    }

    @Override
    public void checkCartItem(Long skuId, Integer isChecked) {
        if (skuId == null || isChecked == null){
            return;
        }
        CartItemVo cartItem = getCartItem(skuId);
        cartItem.setChecked(isChecked == 1 ? true:false);
        BoundHashOperations cartOps = redisCartOps();
        cartOps.put(skuId+"",cartItem);
    }

    @Override
    public void modifyItemNum(Long skuId, Integer num) {
        CartItemVo cartItem = getCartItem(skuId);
        cartItem.setCount(num);
        BoundHashOperations cartOps = redisCartOps();
        cartOps.put(skuId+"",cartItem);
    }

    @Override
    public void delCartItem(Long skuId) {
        BoundHashOperations cartOps = redisCartOps();
        cartOps.delete(skuId+"");
    }

    @Override
    public R getCurrentCartItems() {
        UserCartBo userCart = ThreadLocalUtil.get();
        if (userCart.getUserId() == null){
            return R.error("当前的登录用户不存在");
        }else{
            List<CartItemVo> cartItemList = getCartItemList(CartConstant.CART_REDIS_PREFIX + userCart.getUserId());
            if (CollectionUtils.isEmpty(cartItemList)){
                return R.error("购物车为空");
            }
            List<CartItemVo> itemVoList = cartItemList.stream().filter(x -> x.getChecked()).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(itemVoList)){
                return R.error("购物车没有选中的购物项");
            }
            List<Long> collect = cartItemList.stream().filter(x -> x.getChecked()).map(CartItemVo::getSkuId).collect(Collectors.toList());
            List<CartItemCheckedDto> skus = skuClient.getSkus(collect);
            itemVoList.forEach(x ->{
                if (!CollectionUtils.isEmpty(skus)){
                    for (CartItemCheckedDto checkedDto : skus){
                        if (checkedDto.getSkuId() != null && checkedDto.getSkuId().intValue() == x.getSkuId()){
                            x.setPrice(checkedDto.getPrice());
                        }
                    }
                }
            });
            return R.ok().setData(itemVoList);
        }
    }

    private List<CartItemVo> getCartItemList(String cartKey){
        List<Object> values = redisTemplate.boundHashOps(cartKey).values();
        List<CartItemVo> cartItemVos = JSONObject.parseObject(JSONObject.toJSONString(values), new TypeReference<List<CartItemVo>>() {
        });
        return cartItemVos;
    }

    private BoundHashOperations redisCartOps(){
        BoundHashOperations hashOps = null;
        UserCartBo userCart = ThreadLocalUtil.get();
        if (userCart.getUserId() != null){
            hashOps = redisTemplate.boundHashOps(CartConstant.CART_REDIS_PREFIX + userCart.getUserId());
        }else{
            hashOps = redisTemplate.boundHashOps(CartConstant.CART_REDIS_PREFIX+userCart.getUserKey());
        }
        return hashOps;
    }
}
